﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;

namespace ICeFramework.DataManagement.SQLComparer
{
    public class DBPropertyInfo
    {
        private object _parent;

        public event PropertyAddedEventHandler PropertyAdded;

        private string _propertyName;
        public string PropertyName
        {
            get { return _propertyName; }
            set { _propertyName = value; }
        }

        private Type _propertyType;
        public Type PropertyType
        {
            get { return _propertyType; }
            set { _propertyType = value; }
        }

        private object _propertyValue;
        public object PropertyValue
        {
            get { return _propertyValue; }
            set { _propertyValue = value; }
        }

        private List<DBPropertyInfo> _children = new List<DBPropertyInfo>();
        public List<DBPropertyInfo> Children
        {
            get { return _children; }
            set { _children = value; }
        }

        public DBPropertyInfo(string name, Type type, object value, object parent)
        {
            _propertyName = name;
            _propertyType = type;
            _propertyValue = value;
            _parent = parent;
        }

        public override string ToString()
        {
            return string.Format("Name={0}, Type={1}, Value={2} (PropertiesCount: {3})", _propertyName, _propertyType.ToString(), _propertyValue.ToString(), _children.Count);
        }

        public void GetProperties()
        {
            GetProperties(_propertyValue, _parent);
        }

        private void GetProperties(object instance, object parent)
        {
            if (instance as IList == null && instance as ICollection == null)
            {
                GetObjectProperties(instance, parent);
            }
            else if (instance as IList != null)
            {
                foreach (object obj in (instance as IList))
                {
                    GetObjectProperties(obj, instance);
                }
            }
            else if (instance as ICollection != null)
            {
                foreach (object obj in (instance as ICollection))
                {
                    GetObjectProperties(obj, instance);
                }
            }
        }

        private void GetObjectProperties(object instance, object parent)
        {
            PropertyInfo[] props = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (PropertyInfo property in props)
            {
                DBPropertyInfo info = null;
                try
                {
                    object val = property.GetValue(instance, null);
                    if (!val.Equals(parent))
                    {
                        info = new DBPropertyInfo(property.Name, property.PropertyType, val, instance);
                        _children.Add(info);
                        GetProperties(val, instance);
                    }
                }
                catch { }
                if (info != null)
                {
                    OnPropertyAdded(new PropertyAddedEventArgs(this, info));
                }
            }
        }

        public virtual void OnPropertyAdded(PropertyAddedEventArgs e)
        {
            if (PropertyAdded != null)
            {
                PropertyAdded(this, e);
            }
        }

    }
}
